// 版权所有2010 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package math

// 系数_sin[]和_cos[]可在pkg/math/sin中找到。去

// Sincos返回Sin（x），Cos（x）。
// 
// 特殊情况为：
// Sincos（±0）=±0，1 
// Sincos（±Inf）=NaN，NaN 
// Sincos（NaN）=NaN，NaN 
func Sincos(x float64) (sin, cos float64) {
	const (
		PI4A = 7.85398125648498535156e-1  // 0x3FE921FB400000，Pi/4分为三部分
		PI4B = 3.77489470793079817668e-8  // 0x3E644D00000000，
		PI4C = 2.69515142907905952645e-15 // 0x3CE84898CC5170，
	)
	// 特殊情况
	switch {
	case x == 0:
		return x, 1 // 返回±0.0，1.0 
	case IsNaN(x) || IsInf(x, 0):
		return NaN(), NaN()
	}

	// 使参数为正
	sinSign, cosSign := false, false
	if x < 0 {
		x = -x
		sinSign = true
	}

	var j uint64
	var y, z float64
	if x >= reduceThreshold {
		j, z = trigReduce(x)
	} else {
		j = uint64(x * (4 / Pi)) // x的整数部分/（Pi/4），作为相位角测试的整数
		y = float64(j)           // x的整数部分/（Pi/4），as float 

		if j&1 == 1 { // 将零映射到原点
			j++
			y++
		}
		j &= 7                               // 八分之一模2Pi弧度（360度）
		z = ((x - y*PI4A) - y*PI4B) - y*PI4C // 扩展精度模运算
	}
	if j > 3 { // 在x轴上反射
		j -= 4
		sinSign, cosSign = !sinSign, !cosSign
	}
	if j > 1 {
		cosSign = !cosSign
	}

	zz := z * z
	cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
	sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
	if j == 1 || j == 2 {
		sin, cos = cos, sin
	}
	if cosSign {
		cos = -cos
	}
	if sinSign {
		sin = -sin
	}
	return
}
